package ft.xpf.util;

import java.io.ByteArrayOutputStream;
import java.util.Map;

import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.XPath;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;

/**
 * XML 文档解析工具类
 */
public class XmlParseUtil
{
	/**
	 * OutputFormat.createPrettyPrint()
	 * @param txt
	 * @return
	 * @throws Exception
	 */
	public static String xmlFormatPretty(String txt) throws Exception
	{
		String ret ="";
		if(txt!=null && txt.length()>0)
		{
			Document doc = DocumentHelper.parseText(txt);
			ByteArrayOutputStream os = null;
			
			os = new ByteArrayOutputStream();
			XMLWriter outputter = new XMLWriter(os,OutputFormat.createPrettyPrint());
			outputter.write(doc);
			outputter.close();
			ret = os.toString("UTF-8");
			os.close();
		}
		return ret;
	}
	
	/**
	 * OutputFormat.createCompactFormat()
	 * @param txt
	 * @return
	 * @throws Exception
	 */
	public static String xmlFormatCompact(String txt) throws Exception
	{
		String ret ="";
		if(txt!=null && txt.length()>0)
		{
			Document doc = DocumentHelper.parseText(txt);
			ByteArrayOutputStream os = null;
			
			os = new ByteArrayOutputStream();
			XMLWriter outputter = new XMLWriter(os,OutputFormat.createCompactFormat());
			outputter.write(doc);
			outputter.close();
			ret = os.toString("UTF-8");
			os.close();
		}
		return ret;
	}
	
	/**
	 * 在xml文档中选择特定的路径值<br />
	 * Document.selectSingleNode(Xpath)
	 * @param xml
	 * @param xpath
	 * @return
	 */
	public static String xmlSelectSingle(String xml, String xpath) throws Exception
	{
		String ret = "";
		if(xml==null || xml.length()==0)
		{
			throw new Exception("传入参数xml无效");
		}
		else if(xpath==null || xpath.length()==0)
		{
			throw new Exception("传入参数xpath无效");
		}
		else
		{
			Document doc = DocumentHelper.parseText(xml);
			Element ele = (Element)doc.selectSingleNode(xpath);
			if(ele!=null)
			{
				ret = ele.getText();
			}
		}
		return ret;
	}
	
	/**
	 * 在 XML 文档中选择特定的路径值<br />
	 * 带有 Namespace 的 Map 参数需要事先准备好。<br />
	 * 使用 XPath selectSingleNode(Object) 方法<br />
	 * 注意：调用该方法同样需要 jaxen 包的支持<br />
	 * @param xml 待解析 XML 文档
	 * @param xpath 待解析 xpath 路径
	 * @param nsmap 由 prefix 和 URI 组成的 Namespace 键值对
	 * @return
	 * @throws Exception
	 */
	public static String xmlSelectSingleA(String xml, String xpath, Map<String,String> nsmap)
			throws Exception
	{
		String ret = "";
		
		if(xml==null || xml.length()==0)
		{
			throw new Exception("传入参数 xml 无效");
		}
		else if(xpath==null || xpath.length()==0)
		{
			throw new Exception("传入参数 xpath 无效");
		}
		else
		{
			Document doc = DocumentHelper.parseText(xml);
			XPath xp = DocumentHelper.createXPath(xpath);
			
			if(nsmap!=null && nsmap.size()>0)
			{
				// 加入命名空间
				xp.setNamespaceURIs(nsmap);
			}
			
			Node nodes = xp.selectSingleNode(doc);
			
			if(nodes!=null)
			{
				if(nodes instanceof Element)
				{
					Element el = (Element)nodes;
					String etext = el.getText();
					if(etext!=null && etext.length()>0)
					{
						ret = etext;
					}
				}
				else
				{
					// 找到的节点不是 Element 类型。 // throw new Exception("找到的节点不是 Element 类型。" + xpath);
					// 那么直接使用 Node 取得的 Text 值
					String ntext = nodes.getText();
					if(ntext!=null && ntext.length()>0)
					{
						ret = ntext;
					}
				}
			}
			else
			{
				// 未找到该节点：
				throw new Exception("未找到该节点：" + xpath);
			}
		}
		
		
		return ret;
	}
}
